home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Graphics⁄Sound
/
RTrace-1.0-src
/
triangle.c
< prev
Wrap
Text File
|
1992-08-17
|
7KB
|
174 lines
/*
* Copyright (c) 1988, 1992 Antonio Costa, INESC-Norte.
* All rights reserved.
*
* This code received contributions from the following people:
*
* Roman Kuchkuda - basic ray tracer
* Mark VandeWettering - MTV ray tracer
* Augusto Sousa - overall, shading model
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Antonio Costa, at INESC-Norte. The name of the author and
* INESC-Norte may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "defs.h"
#include "extern.h"
/**********************************************************************
* RAY TRACING - Triangle - Version 7.0 *
* *
* MADE BY : Antonio Costa, INESC-Norte, October 1988 *
* ADAPTED BY : Antonio Costa, INESC-Norte, June 1989 *
* MODIFIED BY: Antonio Costa, INESC-Norte, December 1991 *
**********************************************************************/
/***** Triangle *****/
real
triangle_intersect(position, vector, object)
xyz_ptr position, vector;
object_ptr object;
{
REG real distance, k, k0;
xyz_struct p;
triangle_ptr triangle;
REALINC(triangle_tests);
triangle = (triangle_ptr) object->data;
k = DOT_PRODUCT(*vector, triangle->transf[2]);
if (ABS(k) >= ROUNDOFF)
{
p.x = triangle->coords[0].x - position->x;
p.y = triangle->coords[0].y - position->y;
p.z = triangle->coords[0].z - position->z;
distance = DOT_PRODUCT(p, triangle->transf[2]) / k;
if (distance > threshold_distance)
{
p.x = distance * vector->x + position->x - triangle->coords[0].x;
p.y = distance * vector->y + position->y - triangle->coords[0].y;
p.z = distance * vector->z + position->z - triangle->coords[0].z;
k = DOT_PRODUCT(p, triangle->transf[0]);
k0 = DOT_PRODUCT(p, triangle->transf[1]);
if ((k >= 0.0) AND(k0 >= 0.0) AND(k + k0 <= 1.0))
{
triangle->u_hit = k;
triangle->v_hit = k0;
return distance;
}
return 0.0;
}
return 0.0;
}
return 0.0;
}
void
triangle_normal(position, object, normal)
xyz_ptr position;
object_ptr object;
xyz_ptr normal;
{
REG real t, u, v;
triangle_ptr triangle;
triangle = (triangle_ptr) object->data;
u = triangle->u_hit;
v = triangle->v_hit;
t = 1.0 - u - v;
normal->x = t * triangle->normal[0].x + u * triangle->normal[1].x +
v * triangle->normal[2].x;
normal->y = t * triangle->normal[0].y + u * triangle->normal[1].y +
v * triangle->normal[2].y;
normal->z = t * triangle->normal[0].z + u * triangle->normal[1].z +
v * triangle->normal[2].z;
NORMALIZE(*normal);
}
static void
load_triangle(triangle)
triangle_ptr triangle;
{
int i;
REG real k;
xyz_struct temp[3];
NORMALIZE(triangle->normal[0]);
NORMALIZE(triangle->normal[1]);
NORMALIZE(triangle->normal[2]);
temp[0].x = triangle->coords[1].x - triangle->coords[0].x;
temp[0].y = triangle->coords[1].y - triangle->coords[0].y;
temp[0].z = triangle->coords[1].z - triangle->coords[0].z;
temp[1].x = triangle->coords[2].x - triangle->coords[0].x;
temp[1].y = triangle->coords[2].y - triangle->coords[0].y;
temp[1].z = triangle->coords[2].z - triangle->coords[0].z;
CROSS_PRODUCT(temp[2], temp[0], temp[1]);
NORMALIZE(temp[2]);
k = 1.0 /
(temp[0].x * temp[1].y * temp[2].z + temp[0].y * temp[1].z * temp[2].x +
temp[0].z * temp[1].x * temp[2].y - temp[0].z * temp[1].y * temp[2].x -
temp[0].x * temp[1].z * temp[2].y - temp[0].y * temp[1].x * temp[2].z);
triangle->transf[0].x = (temp[1].y * temp[2].z - temp[1].z * temp[2].y);
triangle->transf[1].x = -(temp[0].y * temp[2].z - temp[0].z * temp[2].y);
triangle->transf[2].x = (temp[0].y * temp[1].z - temp[0].z * temp[1].y);
triangle->transf[0].y = -(temp[1].x * temp[2].z - temp[1].z * temp[2].x);
triangle->transf[1].y = (temp[0].x * temp[2].z - temp[0].z * temp[2].x);
triangle->transf[2].y = -(temp[0].x * temp[1].z - temp[0].z * temp[1].x);
triangle->transf[0].z = (temp[1].x * temp[2].y - temp[1].y * temp[2].x);
triangle->transf[1].z = -(temp[0].x * temp[2].y - temp[0].y * temp[2].x);
triangle->transf[2].z = (temp[0].x * temp[1].y - temp[0].y * temp[1].x);
for (i = 0; i < 3; POSINC(i))
{
triangle->transf[i].x *= k;
triangle->transf[i].y *= k;
triangle->transf[i].z *= k;
}
}
void
triangle_enclose(object)
object_ptr object;
{
REG int i;
xyz_struct temp1, temp2;
triangle_ptr triangle;
triangle = (triangle_ptr) object->data;
if (object->transf != NULL)
{
for (i = 0; i < 3; POSINC(i))
{
transform(object->inv_transf, &(triangle->coords[i]), &temp1);
transform_vector(object->inv_transf, &(triangle->coords[i]),
&(triangle->normal[i]), &temp1, &temp2);
STRUCT_ASSIGN(triangle->coords[i], temp1);
STRUCT_ASSIGN(triangle->normal[i], temp2);
}
FREE(object->transf);
object->transf = NULL;
}
load_triangle(triangle);
STRUCT_ASSIGN(*(object->min), triangle->coords[0]);
STRUCT_ASSIGN(*(object->max), triangle->coords[0]);
for (i = 1; i < 3; POSINC(i))
{
object->max->x = MAX(object->max->x, triangle->coords[i].x);
object->max->y = MAX(object->max->y, triangle->coords[i].y);
object->max->z = MAX(object->max->z, triangle->coords[i].z);
object->min->x = MIN(object->min->x, triangle->coords[i].x);
object->min->y = MIN(object->min->y, triangle->coords[i].y);
object->min->z = MIN(object->min->z, triangle->coords[i].z);
}
/* Adjust dimensions */
object->max->x += threshold_distance;
object->max->y += threshold_distance;
object->max->z += threshold_distance;
object->min->x -= threshold_distance;
object->min->y -= threshold_distance;
object->min->z -= threshold_distance;
}